
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Net;
using MonoTouch.AVFoundation;
using System.IO;
using System.ComponentModel;
using System.Diagnostics;
using MonoTouch.MediaPlayer;

namespace Hanselminutes
{
	public partial class PlayerViewController : UIViewController
	{
		#region Constructors

		// The IntPtr and NSCoder constructors are required for controllers that need 
		// to be able to be created from a xib rather than from managed code

		public PlayerViewController (IntPtr handle) : base(handle)
		{
			Initialize ();
		}

		[Export("initWithCoder:")]
		public PlayerViewController (NSCoder coder) : base(coder)
		{
			Initialize ();
		}

		public PlayerViewController (ShowRepository repo, Show show) : base("PlayerViewController", null)
		{
			_repo = repo;
			_show = show;
			Initialize ();
		}

		void Initialize ()
		{
			Title = "Show " + _show.ShowNumber;
		}

		#endregion

		ShowRepository _repo;
		Show _show;

		WebClient _webClient;
		AVAudioPlayer _audioPlayer;
		MPMoviePlayerController _moviePlayer;
		NSTimer _updateTimer;
		NSTimer _updateTotalTimer;
		double _bytesReceived;
		bool _playing;
		bool _fileDownloaded;
		bool _downloadCompletedSuccessfully;

		
		public override bool CanBecomeFirstResponder {
			get {
				return true;
			}
		}
		
		public override void ViewWillAppear (bool animated)
		{
			base.ViewWillAppear (animated);
			
			this.BecomeFirstResponder();
			
		}
		
		
		
		public override void ViewDidLoad ()
		{
			
			UIApplication.SharedApplication.BeginReceivingRemoteControlEvents();

			commentsView.Layer.CornerRadius = 10;
			titleView.Text = _show.Title;
			descView.Text = _show.OfflineAudioPath;
			
			SetAudioSession (AVAudioSession.CategoryPlayback);
			
			UIHelper.StartInternetActivity();
			_repo.BeginGetComments(_show, comments => {
				InvokeOnMainThread(delegate {
					UIHelper.StopInternetActivity();
					DisplayComments(comments);
				});				
			});
			
			DisplayComments(new Comment[0]);
		}
		
		public override void ViewDidUnload ()
		{
			base.ViewDidUnload ();
			
			UIApplication.SharedApplication.EndReceivingRemoteControlEvents();
		}
		
		
		void DisplayComments(Comment[] comments) {
			var html = @"<html><head></head><body style='background-color:rgb(231,239,192);font-family:Helvetica;font-size:14px;'>";
			
			foreach (var c in comments) {
				
				html += "<div style='padding:3px 0px 3px 0px;border-bottom:solid 1px rgb(216,223,186)'>";
				html += "<strong>" + c.Author + "</strong> ";
				html += c.HtmlText;
				html += "</div>";
				
			}
			
			html += "</body></html>";
			commentsView.LoadHtmlString(html, new NSUrl("http://www.hanselminutes.com"));
		}
		
		#region Outlet Events		

		partial void PlayButtonPressed (UIButton sender)
		{
			if (_audioPlayer == null) {
				StartPlayback();
			}
			else {
				if (_audioPlayer.Playing) {
					PausePlayback ();
				} else {
					ResumePlayback ();
				}
			}
		}

		#endregion

		public void StartPlayback ()
		{
			ResetProgressBar ();
			
			_fileDownloaded = false;
			_downloadCompletedSuccessfully = false;
			
			CancelCurrentAudioPlayback ();
			CancelCurrentClientCalls ();
			
			_playing = false;
			slider.Enabled = false;
			
			if (_show.OfflineAudioAvailable) {
				_fileDownloaded = true;
				PlayAudioFile (_show.OfflineAudioPath);
			} 
			else if (_show.Url.EndsWith(".mp4")) 
			{
				// It's a video - play "Audio" file directly"
				PlayAudioFile (_show.OfflineAudioPath);
			} 
			else 
			{
				UIHelper.StartInternetActivity ();
				StartLoadingScreen ("StartPlayback: Buffering...");
				BeginDownloadingShow ();
			}
		}

		void StartLoadingScreen (string message)
		{
			Console.WriteLine (message);
		}

		void BeginDownloadingShow ()
		{
			_webClient = new WebClient ();
			_webClient.DownloadFileCompleted += (sender, e) =>
			{
				_fileDownloaded = true;
				if (_downloadCompletedSuccessfully) {
					File.Copy (_show.PartialAudioPath, _show.OfflineAudioPath);
				}
				UIHelper.StopInternetActivity ();
			};
			
			_webClient.DownloadProgressChanged += HandleClientDownloadProgressChanged;
			_webClient.DownloadFileAsync (new Uri (_show.Url), _show.PartialAudioPath);
		}

		void CancelCurrentAudioPlayback ()
		{
			if (_audioPlayer != null) {
				if (_audioPlayer.Playing)
					_audioPlayer.Stop ();
				_audioPlayer.Dispose ();
			}
		}

		void CancelCurrentClientCalls ()
		{
			if (_webClient != null) {
				_webClient.CancelAsync ();
				_webClient.Dispose ();
				_webClient = null;
			}
		}

		void HandleClientDownloadProgressChanged (object sender2, DownloadProgressChangedEventArgs e2)
		{
			_bytesReceived = e2.BytesReceived;
			_fileDownloaded = false;
			
			if (e2.ProgressPercentage == 100) {
				_downloadCompletedSuccessfully = true;
			}
			
			//InvokeOnMainThread( delegate {
			//	progressBar.Progress = (float) (e2.ProgressPercentage * 0.01f);	
			//});
			
			if (!_playing && BufferedSignificantly (e2.ProgressPercentage)) {
				PlayAudioFile (_show.PartialAudioPath);
			}
		}

		void PlayAudioFile (string filePath)
		{
			InvokeOnMainThread (delegate {
				
				slider.Enabled = true;
				_playing = true;
								
				
				Console.WriteLine ("Ends with .mp3? " + filePath.EndsWith(".mp3"));
				
				if(filePath.EndsWith(".mp3")){
									
					var pathUrl = NSUrl.FromFilename(filePath);

					_audioPlayer = AVAudioPlayer.FromUrl (pathUrl);
				
					_audioPlayer.BeginInterruption += delegate(object sender, EventArgs e) {
						Console.WriteLine ("Begin Interruptions");
						UpdateViewForPlayerState ();
					};
					_audioPlayer.EndInterruption += delegate(object sender, EventArgs e) {
						Console.WriteLine ("End Interruption");
						ResumePlayback ();
					};
					_audioPlayer.DecoderError += delegate(object sender, AVErrorEventArgs e) { Console.WriteLine ("Decoder Error"); };
					
					_audioPlayer.FinishedPlaying += delegate(object sender, AVStatusEventArgs e) {
						Console.WriteLine ("Finished Playing..." + e.Status);
						_audioPlayer.CurrentTime = 0;
					};
					
					UpdateViewForPlayerInfo ();
					UpdateViewForPlayerState ();
					
					slider.TouchDown += delegate { PausePlayback (); };
					
					slider.ValueChanged += delegate {
						_audioPlayer.CurrentTime = slider.Value;
						UpdateCurrentTime ();
					};
					
					// Start playing selected Podcast
					ResumePlayback ();	
				} else {
					
					var pathUrl = NSUrl.FromString(filePath);

					
					Console.WriteLine ("Playing movie innit..." + pathUrl);
					_moviePlayer = new MPMoviePlayerController(pathUrl);
					_moviePlayer.Fullscreen = true;
					
					var movieView = _moviePlayer.View;
					movieView.Frame = this.View.Bounds;
					
					this.View.AddSubview(movieView);
					
					_moviePlayer.Play();
				}
				
			});
		}

		bool BufferedSignificantly (int ProgressPercentage)
		{
			// Should add in proper logic to buffer the track - for now,
			// when 1% of a track has downloaded - start playing.
			return ProgressPercentage >= 1;
		}

		void ResumePlayback ()
		{
			if (_audioPlayer != null) {
				if (_audioPlayer.Play ()) {
					
					slider.Enabled = true;
					UpdateViewForPlayerState ();
				
				} else {
				
					Console.WriteLine ("Could not play " + _audioPlayer.Url.AbsoluteUrl);
				}
			}
		}

		void PausePlayback ()
		{
			if (_audioPlayer != null) {
				_audioPlayer.Pause ();
				UpdateViewForPlayerState ();
			}
		}

		#region Timer Methods and Updates

		/// <summary>
		/// Handle update timers and button presses.
		/// </summary>
		void UpdateViewForPlayerState ()
		{
			UpdateCurrentTime ();
			
			if (_updateTimer != null)
				_updateTimer.Invalidate ();
			
			if (_updateTotalTimer != null)
				_updateTotalTimer.Invalidate ();
			
			if (!_fileDownloaded) {
				_updateTotalTimer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (0.01), UpdateTotalTime);
			}
			
			if (_audioPlayer.Playing)
				_updateTimer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (0.01), UpdateCurrentTime);
			else
				_updateTimer = null;
			
			modalButton.SetTitle ((_audioPlayer.Playing) ? "Pause" : "Play", UIControlState.Normal);
		}

		#endregion

		/// <summary>
		/// Resets the progress bar.
		/// </summary>
		void ResetProgressBar ()
		{
			//progressBar.Progress = 0;
		}

		#region Audio Helper Methods

		/// <summary>
		/// Converts byte count and bit rate into time in seconds - will use 96kbps as bit rate.
		/// </summary>
		double GetCurrentAudioLength (double byteCount)
		{
			return GetCurrentAudioLength (byteCount, Convert.ToDouble (96));
		}

		/// <summary>
		/// Converts byte count and bit rate into time in seconds.
		/// </summary>
		double GetCurrentAudioLength (double byteCount, double bitRate)
		{
			var bits = byteCount * 8;
			var bitsInBitRate = bits / bitRate;
			var seconds = bitsInBitRate / 1000;
			return seconds;
		}

		/// <summary>
		/// Sets the Audio Session for the iPhone application.
		/// </summary>
		void SetAudioSession (string audioCategory)
		{
			var audioSession = AVAudioSession.SharedInstance ();
			NSError err;
			audioSession.SetActive (true, out err);
			audioSession.SetCategory (audioCategory, out err);
		}

		#endregion


		/// <summary>
		/// Updates the current playing time.
		/// </summary>
		void UpdateCurrentTime ()
		{
			InvokeOnMainThread (delegate {
				currentTime.Text = UIHelper.FormatTimeSpan(_audioPlayer.CurrentTime);				
				slider.Value = (int)_audioPlayer.CurrentTime;
			});
		}

		/// <summary>
		/// Update the Total time from byte count.
		/// </summary>
		void UpdateTotalTime ()
		{
			
			// Update ending time since we're progressively downloading stuff...
			var currentDuration = GetCurrentAudioLength (_bytesReceived);
			
			totalTime.Text = UIHelper.FormatTimeSpan(currentDuration);
			
			slider.MaxValue = (int)currentDuration;
			
			if (_downloadCompletedSuccessfully) {
				totalTime.TextColor = UIColor.Black;
			} else {
				totalTime.TextColor = UIColor.Blue;
			}
		}

		/// <summary>
		/// Update the Total Time from the duration. 
		/// </summary>
		void UpdateViewForPlayerInfo ()
		{
			totalTime.Text = UIHelper.FormatTimeSpan(_audioPlayer.Duration);
			
			slider.MaxValue = (int)_audioPlayer.Duration;
		}	
		
		public override void RemoteControlReceived (UIEvent theEvent)
		{
			//base.RemoteControlReceived (theEvent);
			Debug.WriteLine("Remote control received...");
			
			var type = theEvent.GetType();
			Debug.WriteLine("Type = " + type.ToString());
			
			
			
		}
		
		
	}
}
